package net.maku.custom.biza.service.reveiveable.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.spire.xls.FileFormat;
import com.spire.xls.Workbook;
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import net.maku.custom.biza.controller.reveiveable.query.ReceivablesQuery;
import net.maku.custom.biza.controller.reveiveable.query.ReceivePayDetailQuery;
import net.maku.custom.biza.controller.reveiveable.vo.ReceivablesVO;
import net.maku.custom.biza.controller.reveiveable.vo.ReceivePayDetailVO;
import net.maku.custom.biza.mapper.reveiveable.ReceivablesConvert;
import net.maku.custom.biza.mapper.reveiveable.ReceivablesDao;
import net.maku.custom.biza.mapper.reveiveable.ReceivePayDetailDao;
import net.maku.custom.biza.pojo.reveiveable.ReceivablesEntity;
import net.maku.custom.biza.service.reveiveable.ReceivablesService;
import net.maku.framework.common.page.PageResult;
import net.maku.framework.common.service.impl.BaseServiceImpl;
import net.maku.framework.common.utils.EasyExcelUtils;
import net.maku.framework.security.user.SecurityUser;
import net.maku.framework.security.user.UserDetail;
import net.maku.system.dao.SysDictDataDao;
import net.maku.system.entity.SysRoleEntity;
import net.maku.system.query.SysDictTypeDataQuery;
import net.maku.system.service.SysUserRoleService;
import net.maku.system.vo.SysDictTypeDataVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 应收款
 *
 * @author NULL
 * @since 1.0.0 2022-07-12
 */
@Service
@AllArgsConstructor
public class ReceivablesServiceImpl extends BaseServiceImpl<ReceivablesDao, ReceivablesEntity> implements
        ReceivablesService {
    @Autowired
    private ReceivePayDetailDao receivePayDetailDao;
    @Autowired
    private SysDictDataDao sysDictDataDao;
    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Override
    public PageResult<ReceivablesVO> page(ReceivablesQuery query) {
        UserDetail user = SecurityUser.getUser();
        // 客服和销售能看到关于自己的所有数据
        List<SysRoleEntity> roleList = sysUserRoleService.getRoleList(user.getId());
        SysRoleEntity salesManage = roleList.stream().filter(o -> o.getName().equalsIgnoreCase("SALES_MANAGE")).findFirst().orElse(null);
        // 管理员和销售主管可以看到所有数据
        if (user.getSuperAdmin() != 1 && salesManage == null){
            // 客服和销售能看到关于自己的所有数据
            SysRoleEntity sales = roleList.stream().filter(o -> o.getName().equalsIgnoreCase("SALES")).findFirst().orElse(null);
            SysRoleEntity cs = roleList.stream().filter(o -> o.getName().equalsIgnoreCase("CS")).findFirst().orElse(null);
            if (sales != null){
                query.setSalesId(user.getId());
            }
            if (cs != null){
                query.setCsId(user.getId());
            }
        }
        String idsStr = query.getIdsStr();
        if (StringUtils.isNotEmpty(idsStr)){
            String[] split = StringUtils.split(idsStr,",");
            List<Long> idList = null;
            if (query.getIdList() == null){
                idList = new ArrayList();
            }else{
                idList = query.getIdList();
            }
            List<String> idStrList = Arrays.asList(split);
            List<Long> collect = idStrList.stream().map(o -> Long.valueOf(o)).collect(Collectors.toList());
            idList.addAll(collect);
        }
        IPage<ReceivablesEntity> page1 = getPage(query);
        List<ReceivablesVO> receivablesVOS = baseMapper.selectRelList(page1, query);
        return new PageResult<>(receivablesVOS, page1.getTotal());
    }

    @Override
    public ReceivablesVO selectById(Long id) {
        ReceivablesVO receivablesVO = baseMapper.selectRelById(id);
        ReceivePayDetailQuery query = new ReceivePayDetailQuery();
        query.setReceivablesId(id);
        List<ReceivePayDetailVO> receivePayDetailVOS = receivePayDetailDao.selectRelList(query);
        receivablesVO.setReceivePayDetailVOList(receivePayDetailVOS);
        return receivablesVO;
    }

    private QueryWrapper<ReceivablesEntity> getWrapper(ReceivablesQuery query){
        QueryWrapper<ReceivablesEntity> wrapper = new QueryWrapper<>();

        return wrapper;
    }

    @Override
    public void save(ReceivablesVO vo) {
        ReceivablesEntity entity = ReceivablesConvert.INSTANCE.convert(vo);
        entity.setCreator(SecurityUser.getUserId());
        entity.setCreateTime(new Date());
        baseMapper.insert(entity);
    }

    @Override
    public void update(ReceivablesVO vo) {
        ReceivablesEntity entity = ReceivablesConvert.INSTANCE.convert(vo);
        entity.setUpdater(SecurityUser.getUserId());
        entity.setUpdateTime(new Date());
        updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> idList) {
        removeByIds(idList);
    }

    @Override
    public void downloadInvoice(HttpServletResponse response, List<Long> idList) {
        String templateFileName = "template/invoice.xlsx";
        ReceivablesQuery query = new ReceivablesQuery();
        query.setIdList(idList);
        List<ReceivablesVO> receivablesVOS = baseMapper.selectRelList(query);
        Map<String, Object> map = new HashMap();
        map.put("date", new Date());

        SysDictTypeDataQuery dictRateQuery = new SysDictTypeDataQuery();
        dictRateQuery.setDictType("exchange_rate");
        List<SysDictTypeDataVO> sysDictTypeDataVOS = sysDictDataDao.selectRelList(dictRateQuery);
        for (SysDictTypeDataVO data : sysDictTypeDataVOS){
            if ("USD_GHS".equalsIgnoreCase(data.getDictLabel()) && StringUtils.isNotEmpty(data.getDictLabel())){
                map.put("usdToGhs",data.getDictValue());
            }
            if ("RMB_GHS".equalsIgnoreCase(data.getDictLabel()) && StringUtils.isNotEmpty(data.getDictLabel())){
                map.put("rmbToGhs",data.getDictValue());
            }
        }

        if (CollectionUtil.isNotEmpty(receivablesVOS)){
            BigDecimal totalAmountUsd = new BigDecimal(0);
            BigDecimal totalAmountRmb = new BigDecimal(0);
            BigDecimal totalChargeWeight = new BigDecimal(0);
            BigDecimal totalCnts = new BigDecimal(0);
            BigDecimal totalAmountGhs = new BigDecimal(0);
            for (ReceivablesVO o : receivablesVOS){
                if (StringUtils.isNotEmpty(o.getCnts())) {
                    totalCnts = totalCnts.add(new BigDecimal(o.getCnts()));
                }
                if (StringUtils.isNotEmpty(o.getChargeWeight())) {
                    totalChargeWeight = totalChargeWeight.add(new BigDecimal(o.getChargeWeight()));
                }
                if (StringUtils.isNotEmpty(o.getTotalUsd())) {
                    totalAmountUsd = totalAmountUsd.add(new BigDecimal(o.getTotalUsd()));
                }
                if (StringUtils.isNotEmpty(o.getTotalRmb())) {
                    totalAmountRmb = totalAmountRmb.add(new BigDecimal(o.getTotalRmb()));
                }
                BigDecimal usdGhs = new BigDecimal(0);
                if (StringUtils.isNotEmpty(o.getTotalUsd()) && map.get("usdToGhs") != null
                        ){
                    BigDecimal usd = new BigDecimal(o.getTotalUsd());
                    BigDecimal usdToGhsRate = new BigDecimal(map.get("usdToGhs").toString());
                    usdGhs = usd.multiply(usdToGhsRate);
                }
                BigDecimal rmbGhs = new BigDecimal(0);
                if (StringUtils.isNotEmpty(o.getTotalRmb()) && map.get("rmbToGhs") != null  ){
                    BigDecimal rmb = new BigDecimal(o.getTotalRmb());
                    BigDecimal rmbToGhsRate = new BigDecimal(map.get("rmbToGhs").toString());
                    rmbGhs = rmb.divide(rmbToGhsRate,1,BigDecimal.ROUND_HALF_UP);
                }
                BigDecimal totalGhs = usdGhs.add(rmbGhs);
                o.setTotalGhs(totalGhs.stripTrailingZeros().toPlainString());
                totalAmountGhs = totalAmountGhs.add(totalGhs);

            }
            map.put("totalCnts",totalCnts.stripTrailingZeros().toPlainString());
            map.put("totalChargeWeight",totalChargeWeight.stripTrailingZeros().toPlainString());
            map.put("totalAmountUsd",totalAmountUsd.stripTrailingZeros().toPlainString());
            map.put("totalAmountRmb",totalAmountRmb.stripTrailingZeros().toPlainString());
            map.put("totalAmountGhs",totalAmountGhs.stripTrailingZeros().toPlainString());
            map.put("customerName",receivablesVOS.get(0).getCustomerName());
            map.put("customerMobile",receivablesVOS.get(0).getCustomerMobile());
        }


        byte[] bytes = EasyExcelUtils.wrapDownloadExcel(templateFileName, ExcelTypeEnum.XLSX, map, receivablesVOS, null);
        LambdaUpdateWrapper<ReceivablesEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(ReceivablesEntity::getId,idList);
        updateWrapper.set(ReceivablesEntity::getPickupDate,new Date());
        this.update(updateWrapper);

        try {
            Workbook wb = new Workbook();
            wb.loadFromStream(new ByteArrayInputStream(bytes));
            ServletOutputStream outputStream = response.getOutputStream();
            wb.saveToStream(outputStream, FileFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //DownloadUtils.wrapDownloadFile(new ByteArrayInputStream(bytes), "invoice.xlsx", response);
    }
}